There are two issues here. First, when you run ps | grep ..., the grep process is also shown in the output of ps. The default ps output includes the arguments a process was launched with, not only the process's name. This means that if you run grep foo, and there is a running process called foo, there will be two ps results matching foo: the foo process and the grep itself since it is searching for foo. This is why you get two lines when running ps -f | grep thunderbird.
Now, the [ ] is a regular expression construct which defines a list of characters, a character class. For example, [abc] will match a or b or c. When you run ps -f | grep [t]hunderbird, that class only contains a single character so is equivalent to thunderbird without the brackets. However, the grep process was launched with [t]hunderbird as an argument this time, and not thunderbird. Therefore, its line in the output of ps will contain [t]hunderbird. It will look like this:
terdon 23101 10991 0 16:53 pts/3 00:00:00 grep --color [t]hunderbird
This means that it is not matched when you run ps -f | grep thunderbird since it contains [t]hunderbird and not thunderbird.
This is a common trick to avoid matching the grep process itself when running ps | grep. Another alternative is to run ps -f | grep foo | grep -v grep to exclude the grep. The best approach, however, is to use a program specifically designed for this, pgrep:
$ pgrep -l thunderbird
11330 thunderbird