Wrapping an if around a function call:
This is to decide if the function should be called at all, and is part of the decision making process of your program.
Guard clause in function (early return):
This is to protect against being called with invalid parameters
A guard clause used in this way keeps the function "pure" (your term). It exists only to ensure that the function doesn't break with erroneous input data.
The logic about whether to call the function at all is at a higher level of abstraction, even if only just. It should exist outside the function itself.As DocBrown says, you can have an intermediate function that performs this check, to simplify the code.
This is a good question to ask, and falls within the set of questions that lead to recognising levels of abstraction.Each function should operate at a single level of abstraction, and having both the program logic and the function logic in the function feels wrong to you - this is because they are at different levels of abstraction. The function itself is a lower level.
By keeping these seperate, you ensure that your code will be easier to write, read and maintain.