Both [ and [[ are used to assess what is between [..] or [[..]], can be compared strings and check file types. 
[ is a synonym for  test, [[ is a keyword. 
In doing if [ condicao ] can be said to be equivalent to if test condicao, for [ is a token that will invoke the command test.
The right bracket ], is not strictly necessary, however in more recent versions of Bash is required.
~$ type test
test is a shell builtin
~$ type '['
[ is a shell builtin
~$ type '[['
[[ is a shell keyword
~$ type ']]'
]] is a shell keyword
~$ type ']'
bash: type: ]: not found
[[..]] is more flexible than [..], when using [[..]] some logical errors can be avoided in the script. For example, the operators &&, ||, <, and > work in the [[..]], but not in [..]. 
Take an example:
if [ -f $foo && -f $bar && -f $baz ]          # Erro
if [ -f $foo ] && [ -f $bar ] && [ -f $baz ]  # OK. Cada expressão dentro de um [..] 
if [ -f $foo -a -f $bar -a -f $baz ]          # OK. Tem que usar "-a" na antes da expressão
if [[ -f $foo && -f $bar && -f $baz ]]        # OK!
The difference and when and which to use between [ and [[ according to the Bashfaq - 031 is:
To cut a long story short: test Implements the old, Portable syntax of
  the command. In Almost all shells (the oldest Bourne shells are the
  Exception), [ is a synonym for test (but requires a final argument of
  ]). 
Although all Modern shells have built-in implementations of [,
  there usually still is an External Executable of that name, e.g. /bin/[.
[[ is a new improved version of it, which is a keyword, not a program.
  This has beneficial effects on the Ease of use, as Shown Below.
[[ is understood by Kornshell and BASH (e. g. 2.03), but not by the Older POSIX or Bourne shell.
[....]
When should the new test command [[ be used, and when the old one [?
If Portability to the Bourneshell is a Concern, the old syntax should
  be used. If on the other hand the script requires BASH or Kornshell,
  the new syntax is Much more Flexible.
Although [ and [[ have much in common and share many expression operators such as -f, -s, -n, -z, there are some notable differences. 
Here is a comparison list:

Credits: Bashfaq - 031