The usual approach is to wrap the output of your ccall in a Julia mutable struct that hides the raw pointer, and has a finalizer that calls the C destructor.
For example, ZMQ.jl does this to wrap the raw void* returned by zmq_socket in the C library with a Julia Socket type with a finalizer that calls zmq_close on the pointer.
In general, you rarely want to expose a raw C pointer-based API to the user; always wrap it.