Your binder thread pool is automatically created as part of libBinder's initialization. Specifically, apps forking from Zygote and starting the activity lifecycle call on the ActivityManager - and that's a binder call right there. The low level calls use the ProcessState object, a singleton which - upon construction - calls open_driver and shortly thereafter sets the thread pool. Technically, this is closer to first IPC call - but the point that needs emphasizing is that for App components (activities/services/receivers/providers) there are always such calls , even if you did not explicitly call context.getSystemService().
You can see this for yourself (if your device is rooted):
try ls -l /proc/$pid/fd
for any app $pid, and you will see one of the numbers (descriptors) point to /dev/binder
then do
cd /proc/$pid/task
grep Name */status
and you will see the Binder_.. threads (the thread pool is named).
The only way to start a process without binder is a pure native process (i.e. NDK C project, linking with Bionic). Then, if you actually did want binder you'd either use ProcessState (and IPCThreadState), or manually code the ioctl(2) calls.