I break down the project into the smallest distinct tasks I can. I then go over the list three times.
The first time I go over the list I look for things that I have a lot of experience with. These are things where based on my previous experience, I can make an very precise estimate of the time it takes.
Then I go over the list looking for things that I am unsure about, and I am worried they will take a long time. I spend some time researching each one of these, and break them down into even smaller tasks. That allows me to get a better idea of what exactly is involved, and it will make it easier to approach it later.
The last time I go over the list, I assume that each task will take one programmer one day of work to complete. Sometimes someone can do a whole bunch in one day. That's great. But sometimes a single task has all sorts of hidden nastiness that nobody ever expected, and it will take someone a week to figure it out. It evens out in the end.
This won't give you a very precise estimate. You can't really have a precise estimate. You can never reliably predict exactly what day you will finish something. However, this will give you a very good conservative and accurate estimate. Accuracy and precision are two different things.