I want to write down a proof that comes naturally, in a way. This proof assumes that you can form the quotient of a set modulo an equivalence relation, but does not require powersets. (So it works in any pretopos.)

We have sets $ A $ and $ B $ and a function $ f $ from $ A $ to $ B $. We know that $ f $ is an epimorphism in the category of sets, and we want to prove that $ f $ is a surjection.

Consider the cokernel pair of $ f $, that is the pushout of $ f $ along itself. Just as epimorphisms in an abelian category have trivial cokernels, so epimorphisms in more general categories have trivial cokernel pairs. So this is a natural thing to look at.

$$ \matrix { A & \overset { \textstyle f } \rightarrow & B \\ \llap f \downarrow & & \downarrow \rlap { k _ 1 } \\ B & \underset { \textstyle k _ 0 } \rightarrow & C } $$

The cokernel pair is a set $ C $ defined as a quotient of the disjoint union $ B \uplus B $; if $ y $ is an element of $ B $, then I'll write $ y _ 0 $ and $ y _ 1 $ for elements of $ B \uplus B $. Then we have an equivalence relation on $ B \uplus B $ according to which $ y _ 0 $ and $ y _ 1 $ are equivalent iff $ y $ belongs to the image of $ f $, and no other equivalences exist besides the reflexive ones. (More explicitly, $ y _ i $ and $ z _ j $ are equal iff $ y = z $ and $ i = j $ or $ y = z $ and $ y = f ( x ) $ for some $ x $.) Then $ C $ is the quotient of $ B \uplus B $ under this equivalence relation. The cokernel pair also comes equipped with two inclusion/quotient maps from $ B $, while I'll call $ k _ 0 $ and $ k _ 1 $; $ k _ i $ maps $ y $ to the equivalence class of $ y _ i $ in $ C $.

Given an element $ x $ in $ A $, $ k _ 0 ( f ( x ) ) = k _ 1 ( f ( x ) ) $ in $ C $ because $ f ( x ) $ is in the image of $ f $. So since $ f $ is an epimorphism, $ k _ 0 = k _ 1 $. This means that for every element $ y $ of $ B $, $ k _ 0 ( y ) = k _ 1 ( y ) $, so $ y $ is in the image of $ f $.

So $ f $ is surjective.