CREATE TABLE tb2 AS 
SELECT c1, c2, c3
FROM   tb1
WHERE  c1 = '1'
AND    c3 <> ''
UNION ALL
SELECT c1, c2, c4
FROM   tb1
WHERE  c1 = '1'
AND    c4 <> '';
- Use UNION ALLunless you want to eliminate possible duplicates. Faster. The result is different if duplicates occur!
- No need for a subquery.
- Use CREATE TABLE ASinstead ofSELECT INTO. Per documentation:
This command is functionally similar to SELECT INTO, but it is
  preferred since it is less likely to be confused with other uses of
  the SELECT INTO syntax. Furthermore, CREATE TABLE AS offers a superset
  of the functionality offered by SELECT INTO.
- The single quotes around '1'indicate you are storing numeric data as string type. If so, that's not good. Consider appropriate data types ...
Alternative with CTE
If the table is big, this alternative with a CTE will be probably be faster, since we only read once from it.
Also including additional requests from comment, add column, add pk:
CREATE TABLE tb2 AS 
WITH cte AS (
   SELECT c1, c2, c3, c4
   FROM   tb1
   WHERE  c1 = '1'
   AND   (c3 <> '' OR c4 <> '')
   )
SELECT c1, c2, c3, NULL::text AS new_column  -- add new column
FROM   cte
WHERE  c3 <> ''
UNION ALL
SELECT c1, c2, c4, NULL
FROM   cte
WHERE  c4 <> '';
-- add primary key:
ALTER TABLE tb2 ADD CONSTRAINT tb2_pkey PRIMARY KEY(???);
If the table is big, you might want to increase temp_buffers setting (for the session only). More info in this related answer:
How to delete duplicate entries?
If you need to run this often (and don't mind the small penalty on write opertaions), and if you can define a superset of rows that eliminates large parts of the rest, I would suggest a partial index ...